package com.expdatacloud.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 初始化数据源，进行装配
 * @author jie
 * @date 2019/10/29 -13:37
 */
@Configuration
@MapperScan(basePackages = DynamicDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "oracleSqlSessionFactory")
public class DynamicDataSourceConfig implements EnvironmentAware {

    // 默认数据源
    private DataSource defaultDataSource;

    //第二数据源
    private DataSource secondDataSource;

    static final String PACKAGE = "com.expdatacloud.mapper";

    private static final String MAPPER_LOCATION = "classpath:mapper/*.xml";

    private static final String DEFAULT_ENV_PATH = "oracle.datasource.datasource1";

    private static final String SECOND_ENV_PATH = "oracle.datasource.datasource2";

    private static final String DEFAULT_DATABASE = "DSA";

    private static final String SECOND_DATABASE = "DSB";

    @Override
    public void setEnvironment(Environment environment) {
        try {
            initDefaultDatasource(environment);
        } catch (Exception e) {
            System.out.println("创建主数据库失败，原因：" + e);
        }

        try {
            initOtherDatasource(environment);
        } catch (Exception e) {
            System.out.println("创建第二数据库失败，原因：" + e);
        }
    }

    private void initDefaultDatasource(Environment environment) throws Exception {
        // 读取主数据源
        defaultDataSource = buildDruidDataSource(environment,DEFAULT_ENV_PATH);
        DataSourceHolder.dataSourceIds.add(DEFAULT_DATABASE);
    }

    private void initOtherDatasource(Environment environment) throws Exception {
        // 读取第二数据源
        secondDataSource = buildDruidDataSource(environment,SECOND_ENV_PATH);
        DataSourceHolder.dataSourceIds.add(SECOND_DATABASE);
    }

    //拼装数据源
    private DruidDataSource buildDruidDataSource(Environment environment, String envPath) throws Exception {


        Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment);
        Binder binder = new Binder(sources);
        BindResult<Properties> bindResult = binder.bind(envPath, Properties.class);
        Properties properties= bindResult.get();

        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setDriverClassName(properties.getProperty("driverClass"));
        dataSource.setUrl(properties.getProperty("url"));
        dataSource.setUsername(properties.getProperty("username"));
        dataSource.setPassword(properties.getProperty("password"));
        //需要的话可以解开
       /* dataSource.setMaxActive(Integer.parseInt(propertyResolver.getProperty("maxActive")));
        dataSource.setMinIdle(Integer.parseInt(propertyResolver.getProperty("minIdle")));
        dataSource.setMaxWait(Long.parseLong(propertyResolver.getProperty("maxWait")));
        dataSource.setPoolPreparedStatements(Boolean.parseBoolean(propertyResolver.getProperty("poolPreparedStatements")));
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(
                Integer.parseInt(propertyResolver.getProperty("maxPoolPreparedStatementPerConnectionSize")));
        dataSource.setKeepAlive(Boolean.parseBoolean(propertyResolver.getProperty("keepAlive")));
        dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(propertyResolver.getProperty("minEvictableIdleTimeMillis")));
        dataSource.setValidationQuery(propertyResolver.getProperty("validationQuery"));
        dataSource.setTestWhileIdle(Boolean.parseBoolean(propertyResolver.getProperty("testWhileIdle")));
        dataSource.setFilters(propertyResolver.getProperty("filters"));*/

        return dataSource;
    }

    @Bean(name = "dataSource")
    public DynamicDataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();

        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);

        // 配置多数据源
        Map<Object, Object> dbMap = new HashMap<Object, Object>();

        dbMap.put(DEFAULT_DATABASE,defaultDataSource);
        dbMap.put(SECOND_DATABASE,secondDataSource);

        dynamicDataSource.setTargetDataSources(dbMap);

        return dynamicDataSource;
    }

    @Primary
    @Bean(name = "oracleTransactionManager")
    public DataSourceTransactionManager oracleTransactionManager() throws SQLException {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
        transactionManager.setNestedTransactionAllowed(true);
        transactionManager.setRollbackOnCommitFailure(true);
        return transactionManager;
    }

    @Primary
    @Bean(name = "oracleSqlSessionFactory")
    public SqlSessionFactory oracleSqlSessionFactory(DataSource dynamicDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(MAPPER_LOCATION));
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setUseGeneratedKeys(true);
        configuration.setUseColumnLabel(true);
        configuration.setJdbcTypeForNull(null);
        sessionFactory.setConfiguration(configuration);
        return sessionFactory.getObject();
    }
}